package com.example.rbac.config;

import com.example.rbac.entity.Menu;
import com.example.rbac.entity.Role;
import com.example.rbac.entity.User;
import com.example.rbac.service.MenuService;
import com.example.rbac.service.UserService;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * shiro配置类,从数据库获取用户密码和角色权限进行验证
 * Created by Administrator on 2017/9/25.
 */
public class Realm extends AuthorizingRealm {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private UserService userService;
    @Autowired
    private MenuService menuService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("权限认证方法：MyShiroRealm.doGetAuthenticationInfo()");
        User token = (User) SecurityUtils.getSubject().getPrincipal();
        String userId = token.getId();
        logger.info("userId{}",token);
        //根据用户id查询对应的角色id
        List<String> roleIds = userService.findRoleByUserId(userId);
        //根据多个角色id查询对应的角色
        List<Role> roleList = userService.findRoleById(roleIds);
        logger.info("roleList{}", roleList);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        //获取角色列表，添加到shiro的角色验证
        Set<String> roleSet = Sets.newHashSet();
        for (Role role: roleList) {
            roleSet.add(role.getRoleName());
        }
        info.setRoles(roleSet);

        //根据角色获取对应的权限,添加到shiro的权限验证
        List<String> menuIdList = menuService.findMenuByRoleId(roleIds);
        List<Menu> menuList = menuService.findMenuByMenuId(menuIdList);
        logger.info("menuList={}", menuIdList);
        Set<String> permissionSet = Sets.newHashSet();
        for (Menu menu : menuList) {
            permissionSet.add(menu.getPermission());
        }
        info.setStringPermissions(permissionSet);
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        System.out.println("身份认证方法：MyShiroRealm.doGetAuthenticationInfo()");
        Map<String, String> users = Maps.newLinkedHashMap();
        String username = authcToken.getPrincipal().toString();
        String password = new String((char[])authcToken.getCredentials());
        users.put("username", username);
        users.put("password", password);
        logger.info("msg={}", users);
        // 从数据库获取对应用户名密码的用户
        User user = userService.findUserByUserNameAndPwd(users);
        if (null == user) {
            throw new AccountException("帐号或密码不正确！");
        } else if (user.getState().equals("0")) {
            /**
             * 如果用户的status为禁用。那么就抛出<code>DisabledAccountException</code>
             */
            throw new DisabledAccountException("帐号已经禁止登录！");
        } else {
            //更新登录时间 last login time
            user.setUpdateTime(new Date());
          /*  userService.updateById(user);*/
        }
        return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
    }
}
